﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using ZebraCoreLib.Framework;
using ZebraCoreLib.ZebraException;
using System.Text.RegularExpressions;
using ZebraCoreLib.DBHelper;
using System.Data.SqlClient;
using System.Data.Common;
using System.Collections;

namespace ZebraCoreLib.BasBiz
{
    public enum ValidationType
    {
        Add,
        Update,

    }


    //public abstract class BasBizService
    //{
    //}
    public abstract class BasBizService<T>
    {
        protected bool PrepareCommand = true;
        protected SQLHelper SQLHelper = SQLHelper.CreateInstance();
        public DbTransaction Transation = null;
    

        [ZebraField(Title = "序号", DataField = "null")]
        public int RowNumber { get; set; }
        

        public virtual T Add(T entity)
        {
            //处理自动编号

            var properties = BizServiceHelper.GetZebraFieldProperties(entity);
            object keyValue = null;
            foreach (var p in properties)
            {
                ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                //处理自动编号
                if (attr.IsAutoID)
                {
                    p.SetValue(entity, SQLBuilder.GetAutoID(), null);
                }
                if (attr.IsPrimaryKey)
                {
                    keyValue = p.GetValue(this, null);
                }
            }
            //外键值关联
            foreach (var p in properties)
            {
                ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                //处理自动编号

                //处理外键值关联
                if (!string.IsNullOrEmpty(attr.Foreignkey))
                {
                    var details = ((IList)p.GetValue(entity, null));
                    foreach (var d in details)
                    {
                        if (Transation != null)
                            BizServiceHelper.SetFieldValue(d, "Transation", Transation);
                        BizServiceHelper.SetZebraFieldValue(d, attr.Foreignkey, keyValue);
                        BizServiceHelper.InvokeBizObjectMethod(d, "Add", new object[] { d });
                    }
                }
            }
            //添加到数据库
            AddEntityToDB(entity);

            return entity;
        }

        public virtual void Delete(T entity)
        {
            DbCommand command = null;
            if (Transation != null)
                command = SQLHelper.CreateCommand();
            else
                command = Transation.Connection.CreateCommand();
            SQLBuilder sqlbuider = new SQLBuilder();
            sqlbuider.BuildDeleteCommand(entity, command);

            //3）执行SQL语句，存储数据
            command.ExecuteNonQuery();
            if (Transation == null)
                SQLHelper.CloseConnection(command.Connection);

        }


        public virtual T Update(T entity)
        {
            var properties = BizServiceHelper.GetZebraFieldProperties(entity);
            object keyValue = null;
            foreach (var p in properties)
            {
                ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                //处理自动编号
                if (attr.IsPrimaryKey)
                {
                    keyValue = p.GetValue(this, null);
                }
            }
            //外键值关联
            foreach (var p in properties)
            {
                ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                //处理外键值关联
                if (!string.IsNullOrEmpty(attr.Foreignkey))
                {
                    var details = ((IList)p.GetValue(entity, null));
                    foreach (var d in details)
                    {
                        if (Transation != null)
                            BizServiceHelper.SetFieldValue(d, "Transation", Transation);
                        BizServiceHelper.SetZebraFieldValue(d, attr.Foreignkey, keyValue);
                        BizServiceHelper.InvokeBizObjectMethod(d, "Update", new object[] { d });
                    }
                }
            }

            //1）验证数据合法性
            ZebraDataException exception = Validation(entity, ValidationType.Update);
            //如果数据异常，则抛出错误信息。
            if (exception.ErrorCount > 0)
                throw exception;
            DbCommand command = null;
            if (Transation == null)
                command = SQLHelper.CreateCommand();
            else
                command = Transation.Connection.CreateCommand();
            SQLBuilder sqlbuider = new SQLBuilder();
            sqlbuider.BuildUpdateCommand(entity, command);


            //3）执行SQL语句，存储数据
            command.ExecuteNonQuery();
            if (Transation == null)
                SQLHelper.CloseConnection(command.Connection);
            return entity;
        }

        public virtual List<T> List(ListFlags flags)
        {
            int pageCount = 0;
            return List("", flags, 0, 0, out pageCount);
        }
        public virtual List<T> List(string parameters)
        {
            int pageCount = 0;
            return List(parameters, ListFlags.Master, 0, 0, out pageCount);
        }

        public virtual List<T> List(string parameters, ListFlags falgs)
        {
            int pageCount = 0;
            return List(parameters, falgs, 0, 0, out pageCount);
        }
        public virtual List<T> List(string parameters, int pageIndex, int pageSize, out int pageCount)
        {
            return List(parameters, ListFlags.Master, pageIndex, pageSize, out pageCount);
        }
        public virtual List<T> List(string parameters, ListFlags flags, int pageIndex, int pageSize, out int pageCount)
        {
           

            pageCount = 0;
            bool isCache=false;
            string cacheKey = "";
            var class_attributes = this.GetType().GetCustomAttributes(typeof(ZebraBizObjectAttribute), true);
            if (class_attributes != null)
            {
                var attr = class_attributes[0] as ZebraBizObjectAttribute;
                isCache = attr.IsCacheData;
                if (isCache)
                {
                    cacheKey=attr.TableName + "." +  parameters;
                    if (BizServiceHelper.bizObjectCache[cacheKey] != null)
                        return (BizServiceHelper.bizObjectCache[cacheKey] as List<T>);

                }
            }
            SQLBuilder sqlbuider = new SQLBuilder();

            List<string> commandText = new List<string>();// sqlbuider.BuildSelectCommandText(this, parameters);
            if (pageSize > 0)
            {
                commandText = sqlbuider.BuildSelectCommandTextWithPage(this, parameters, pageIndex, pageSize);
                pageCount = SQLHelper.ExecuteScalar<int>(commandText[1]);

                pageCount = pageCount / pageSize;
                if ((pageCount % pageSize) != 0)
                    pageCount++;
            }
            else
                commandText.Add(sqlbuider.BuildSelectCommandText(this, parameters));
            List<T> bizObjectList = SQLHelper.ExecuteObject<T>(commandText[0]);

            if ((flags | ListFlags.Details) == ListFlags.Details)
            {
                foreach (var obj in bizObjectList)
                {
                    var properties = BizServiceHelper.GetZebraFieldProperties(obj);
                    object keyValue = null;
                    foreach (var p in properties)
                    {
                        ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                        if (attr.IsPrimaryKey)
                        {
                            keyValue = p.GetValue(obj, null);
                        }
                    }
                    //处理明细表
                    foreach (var p in properties)
                    {
                        ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                        //处理外键值关联
                        if (!string.IsNullOrEmpty(attr.Foreignkey))
                        {
                            string detailsParameters = attr.Foreignkey + "='" + keyValue + "'";
                            var detailsTypes = p.PropertyType.GetGenericArguments();
                            if (detailsTypes != null && detailsParameters.Length > 0)
                            {
                                var detailType = detailsTypes[0];
                                object detailsObj = Activator.CreateInstance(detailType);
                                IList listDetails = BizServiceHelper.InvokeBizObjectMethod(detailsObj, "List", new Type[] { typeof(string), typeof(ListFlags) }, new object[] { detailsParameters, ListFlags.Details }) as IList;
                                BizServiceHelper.SetZebraFieldValue(obj, p.Name, listDetails);
                            }
                        }
                    }
                }
            }
            if (true)
            {

                foreach (var bizObject in bizObjectList)
                {
                    var properties = BizServiceHelper.GetZebraFieldProperties(bizObject);
                    foreach (var p in properties)
                    {
                        ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
                        if (!string.IsNullOrEmpty(attr.Relationship))
                        {
                            string[] relationShipText = attr.Relationship.Split('=');
                            string field1 = relationShipText[0];
                            string field2 = relationShipText[1];

                            var relationShipProperty = properties.Where(x => x.Name.Equals(field2, StringComparison.OrdinalIgnoreCase)).Single();
                            string relationShipValue = relationShipProperty.GetValue(bizObject, null) == null ? "" : relationShipProperty.GetValue(bizObject, null).ToString();
                            if (!string.IsNullOrEmpty(relationShipValue))
                            {
                                string relationShipParameters = field1 + "='" + relationShipValue + "'";

                                var relationShipType = p.PropertyType;
                                object relationObj = Activator.CreateInstance(relationShipType);
                                IList listRelation = BizServiceHelper.InvokeBizObjectMethod(relationObj, "List", new Type[] { typeof(string), typeof(ListFlags) }, new object[] { relationShipParameters, ListFlags.Relationship }) as IList;
                                if (listRelation != null && listRelation.Count > 0)
                                {
                                    BizServiceHelper.SetZebraFieldValue(bizObject, p.Name, listRelation[0]);
                                }
                            }


                            // keyValue = p.GetValue(obj, null);
                        }

                    }
                }

            }

            //if (bizObjectList !=null && bizObjectList.Count > 0)
            //{
            //    //构造有Relationship的属性
            //    var properties = BizServiceHelper.GetZebraFieldProperties(bizObjectList[0]);
            //    List<PropertyInfo> relationshipPropertyList = new List<PropertyInfo>();
            //    foreach (var p in properties)
            //    {
            //        ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
            //        if (!string.IsNullOrEmpty(attr.Relationship))
            //        {
            //            relationshipPropertyList.Add(p);
            //        }
            //    }
            //    if (relationshipPropertyList.Count > 0)
            //    {
            //        Hashtable cacheRelationObject = new Hashtable();

            //        foreach (var bizObject in bizObjectList)
            //        {
            //            foreach (var p in relationshipPropertyList)
            //            {
            //                ZebraFieldAttribute attr = BizServiceHelper.GetZebraFieldAttribute(p);
            //                string[] relationShipText = attr.Relationship.Split('=');
            //                string field1 = relationShipText[0];
            //                string field2 = relationShipText[1];

            //                var relationShipProperty = properties.Where(x => x.Name.Equals(field2, StringComparison.OrdinalIgnoreCase)).Single();
            //                string relationShipValue = relationShipProperty.GetValue(bizObject, null) == null ? "" : relationShipProperty.GetValue(bizObject, null).ToString();
            //                if (!string.IsNullOrEmpty(relationShipValue))
            //                {
            //                    string relationShipParameters = field1 + "='" + relationShipValue + "'";
            //                    //if (cacheRelationObject[relationShipParameters] != null)
            //                    //{
            //                    //}
            //                    //else
            //                    //{
            //                        var relationShipType = p.PropertyType;
            //                        object relationObj = Activator.CreateInstance(relationShipType);
            //                        IList listRelation = BizServiceHelper.InvokeBizObjectMethod(relationObj, "List", new Type[] { typeof(string), typeof(ListFlags) }, new object[] { relationShipParameters, ListFlags.Relationship }) as IList;
            //                        if (listRelation != null && listRelation.Count > 0)
            //                        {
            //                            BizServiceHelper.SetZebraFieldValue(bizObject, p.Name, listRelation[0]);
            //                        }
            //                    //}
            //                }

            //            }
            //        }
            //    }

            //}
            if (isCache)
                BizServiceHelper.bizObjectCache[cacheKey] = bizObjectList;
            return bizObjectList;
        }



        private void AddEntityToDB(object entity)
        {
            //1）验证数据合法性
            ZebraDataException exception = Validation(entity, ValidationType.Add);
            //如果数据异常，则抛出错误信息。
            if (exception.ErrorCount > 0)
                throw exception;

            //2）构建Insert SQL语句
            DbCommand command = null;
            if (Transation == null)
                command = SQLHelper.CreateCommand();
            else
            {
                command = Transation.Connection.CreateCommand();
                command.Transaction = Transation;
            }
            SQLBuilder sqlbuider = new SQLBuilder();

            sqlbuider.BuildInsertCommand(entity, command);
            //if (PrepareCommand)
            //    command.Prepare();

            //3）执行SQL语句，存储数据
            command.ExecuteNonQuery();
            if (Transation == null)
                SQLHelper.CloseConnection(command.Connection);
            //SQLHelper.CloseConnection(command.Connection);
        }


        public virtual ZebraDataException Validation(object entity, ValidationType type)
        {
            var ps = BizServiceHelper.GetZebraFieldProperties(entity);
            ZebraDataException data_exception = new ZebraDataException();
            string update_sql = "";
            foreach (var p in ps)
            {
                object oValue = p.GetValue(entity, null);

                var attr = BizServiceHelper.GetZebraFieldAttribute(p);
                string sValue = oValue == null ? "" : oValue.ToString();
                if (attr.MinSize > 0 && sValue.Length < attr.MinSize)
                {
                    data_exception.MessagePoor.Add(attr.Title + "字段长度必须大于" + attr.MinSize);
                }
                if (attr.MaxSize > 0 && sValue.Length > attr.MaxSize)
                {
                    data_exception.MessagePoor.Add(attr.Title + "字段长度必须小于" + attr.MaxSize);
                }
                if (attr.IsRequired && string.IsNullOrEmpty(sValue))
                {
                    data_exception.MessagePoor.Add(attr.Title + "必填");
                }
                if (!string.IsNullOrEmpty(attr.ValidationRegExpress) && !Regex.IsMatch(sValue, attr.ValidationRegExpress))
                {
                    data_exception.MessagePoor.Add(string.Format(attr.OnErrorDescription, sValue));
                }
                if (attr.IsPrimaryKey && type == ValidationType.Update)
                {
                    update_sql = " and " + (string.IsNullOrEmpty(attr.DataField) ? p.Name : attr.DataField) + "!='" + p.GetValue(entity, null) + "'";
                }
                if (attr.UserScopeKey)
                {
                    PropertyInfo sucode_p = ps.Where(x => x.Name.Equals("sucode", StringComparison.CurrentCultureIgnoreCase)).Single();
                    if (sucode_p != null)
                    {
                        string sucode = sucode_p.GetValue(entity, null).ToString();
                        string field_value = p.GetValue(entity, null).ToString();
                        string field_name = string.IsNullOrEmpty(attr.DataField) ? p.Name : attr.DataField;

                        string tableName = typeof(T).Name;
                        var class_attributes = typeof(T).GetCustomAttributes(typeof(ZebraBizObjectAttribute), true);
                        if (class_attributes != null)
                        {
                            tableName = (class_attributes[0] as ZebraBizObjectAttribute).TableName;
                        }

                        string sql = "select count(*) from " + tableName + " where sucode='" + sucode + "' and " + field_name + "='" + field_value + "'";
                        sql += update_sql;
                        int repeatCount = SQLHelper.ExecuteScalar<int>(sql);
                        if (repeatCount >= 1)
                        {
                            data_exception.MessagePoor.Add(attr.Title + "已经存在值" + field_value);
                            //这里可以发出系统信息警告,记录信息
                        }

                    }
                }



            }
            return data_exception;

        }

        //public virtual ZebraDataException Validation (T entity)
        //{
        //    return Validation(entity as object);
        //}


    }
}
